package image

// RGBA r g b a
type RGBA struct {
	R, G, B, A uint8
}

// Image 图片
type Image struct {
	RGBA          [][]RGBA
	Width, Height int
}

// IConvertRGBA2Gray ..
type IConvertRGBA2Gray interface {
	Convert(rgba *RGBA) uint8
}

// SimpleConvertRGBA2Gray ..
type SimpleConvertRGBA2Gray uint8

// Convert ..
func (i SimpleConvertRGBA2Gray) Convert(rgba *RGBA) (gray uint8) {
	gray = uint8(float32(rgba.R)*0.3 + float32(rgba.G)*0.59 + float32(rgba.B)*0.11)
	return
}

// Copy ..
func (i *Image) Copy(ix, iy int, j *Image, x, y, w, h int) {
	if j == nil {
		return
	}
	if x >= j.Width || x >= i.Width || y >= j.Height || y >= i.Height {
		return
	}
	miw := i.Width - ix
	mih := i.Height - iy
	mjw := j.Width - x
	mjh := j.Height - y
	if w > miw {
		w = miw
	}
	if w > mjw {
		w = mjw
	}
	if h > mih {
		h = mih
	}
	if h > mjh {
		h = mjh
	}
	for wi := 0; wi < w; wi++ {
		for hi := 0; hi < h; hi++ {
			i.RGBA[ix+wi][iy+hi] = j.RGBA[x+wi][y+hi]
		}
	}
}

// Graying 灰度图
func (i *Image) Graying(iConvertRGBA2Gray IConvertRGBA2Gray) *Image {
	if iConvertRGBA2Gray == nil {
		return nil
	}
	var gray uint8
	for x := 0; x < i.Width; x++ {
		for y := 0; y < i.Height; y++ {
			gray = iConvertRGBA2Gray.Convert(&i.RGBA[x][y])
			i.RGBA[x][y].R = gray
			i.RGBA[x][y].G = gray
			i.RGBA[x][y].B = gray
		}
	}
	return i
}

// HistGram 获取直方图数组
func (i *Image) HistGram(iConvertRGBA2Gray IConvertRGBA2Gray) []int {
	histGram := make([]int, 256)
	if iConvertRGBA2Gray == nil {
		iConvertRGBA2Gray = SimpleConvertRGBA2Gray(0)
	}
	var gray uint8
	for x := 0; x < i.Width; x++ {
		for y := 0; y < i.Height; y++ {
			if i.RGBA[x][y].R != i.RGBA[x][y].G || i.RGBA[x][y].G != i.RGBA[x][y].B {
				gray = iConvertRGBA2Gray.Convert(&i.RGBA[x][y])
			} else {
				gray = i.RGBA[x][y].R
			}
			histGram[int(gray)]++
		}
	}
	return histGram
}

// HistGramBuilder ..
type HistGramBuilder struct {
	IConvertRGBA2Gray
	BackgroundColor *RGBA
	Color           *RGBA
}

// SaveHistGram ..
func (i *Image) SaveHistGram(filePath string, image *HistGramBuilder) error {
	if image == nil {
		image = new(HistGramBuilder)
	}
	if image.Color == nil {
		image.Color = &RGBA{0, 0, 0, 0xFF}
	}
	if image.BackgroundColor == nil {
		image.BackgroundColor = &RGBA{0xFF, 0xFF, 0xFF, 0xFF}
	}
	img := New(256, 200, image.BackgroundColor)
	histGram := i.HistGram(image.IConvertRGBA2Gray)
	var max, drawNum int
	for _, v := range histGram {
		if max < v {
			max = v
		}
	}
	colMax := float32(max) * 1.2
	for x := 0; x < img.Width; x++ {
		drawNum = int(float32(histGram[x]) * 200 / colMax)
		for y := 0; y < drawNum; y++ {
			img.RGBA[x][199-y] = *image.Color
		}
	}
	return img.SaveAsJPEG(filePath, 100)
}

// DGraying ..
func (i *Image) DGraying() *Image {
	sc := SimpleConvertRGBA2Gray(0)
	return i.Graying(sc)
}

// SaveAsPNG ..
func (i *Image) SaveAsPNG(filePath string) error {
	return saveAsPNG(filePath, i)
}

// SaveAsJPEG ..
func (i *Image) SaveAsJPEG(filePath string, quality int) error {
	return saveAsJPEG(filePath, i, quality)
}
